/**
 * Created by moyu on 2017/4/7.
 */

const renderer = require('express')();
const wrap = require('express-async-wrap');
const moment = require('moment');
const ObjectId = require('mongodb').ObjectId;
const articleDB = require('../db/article');
const cheerio = require('cheerio');

const FORMAT = 'YYYY-MM-DD HH:mm';

const sliceContent = (content) => {
    const SUMMARY_MARKUP_NUM = 5;
    const $ = cheerio.myLoad(content, {decodeEntities: false});
    const $children = $.children();
    let html = '';
    for (let i = 0; i < $children.length && i < SUMMARY_MARKUP_NUM; i++) {
        html += $children.eq(i).outerHTML;
    }
    return html;
};

const renderPosts = (res, page, data) => {
    page = page || 1;
    let size = Number(conf.posts ? conf.posts.size : 8), N = Number(conf.posts ? conf.posts.pageCount : 3);
    let segNo = Math.ceil(page / N);

    articleDB.get().then(col => {
        col.find().sort({top: -1, time: -1}).toArray((err, docs) => {
            if (err) {
                res.send(err);
                return console.error(err);
            }
            const all = docs;
            const posts = all.slice((page - 1) * size, page * size);
            let recentCount = Number(conf.sidebar ? conf.sidebar.recentCount : 6),
                tagCount = Number(conf.sidebar ? conf.sidebar.tagCount : 6)

            Promise.all([
                articleDB.recentArticles(recentCount),
                articleDB.findSomeTags(tagCount)
            ]).then(vals => {
                let tags = vals[1],
                    recent = vals[0];
                res.render("index", Object.assign({}, data, {
                    notitle: true,
                    articles: posts.map(post => ({
                        title: post.title, time: moment(post.time).format(FORMAT),
                        summary: sliceContent(post.content), tags: post.tags, id: post._id,
                        top: post.top
                    })),
                    page: {
                        from: N * segNo - N + 1,
                        to: Math.min(Math.ceil(all.length / size), N * segNo),
                        curr: page,
                        total: Math.ceil(all.length / size),
                    },
                    sidebar: {
                        tags: tags,
                        recent: recent
                    }
                }))
            })
        });
    })
};

renderer.use((req, res, next) => {
    req.login = !!(req.session && req.session.login);
    next();
});

renderer.all('/page', (req, res) => res.redirect("/page/1"));
renderer.all('/page/:page', (req, res, next) => {
    let page = req.params.page
    if (isNaN(page)) {
        next();
    } else {
        renderPosts(res, Number(page), {
            title: '首页',
            login: req.login,
        })
    }
});

renderer.all('/', (req, res) => {
    // console.log(req.params.page)

    renderPosts(res, 1, {
        title: '首页',
        login: req.login,
    });
});

renderer.all('/login', (req, res) => {
    if (req.login) {
        res.redirect("/");
        return;
    }
    res.render("login", {
        title: "登录",
        login: req.login,
        active: "login"
    });
});

renderer.all('/article/:id', (req, res) => {
    let id = req.params.id;
    // console.log(id);
    articleDB.get().then(col => {
        col.findOne({_id: ObjectId(id)}, (err, doc) => {
            if (err) {
                res.send(err);
            } else {
                if (!doc) {
                    res.redirect("/");
                    return;
                }
                doc.time = moment(doc.time).format(FORMAT);
                doc.id = doc._id;
                res.render('article', {
                    title: doc.title,
                    article: doc,
                    login: req.login,
                    notitle: true
                });
            }
        })
    })
})


renderer.all('/tag', (req, res) => {
    let recentCount = Number(conf.sidebar ? conf.sidebar.recentCount : 6),
        tagCount = Number(conf.sidebar ? conf.sidebar.tagCount : 6);
    Promise.all([
        articleDB.recentArticles(recentCount),
        articleDB.findSomeTags(Infinity)
    ]).then(vals => {
        let tags = vals[1],
            recent = vals[0];


        res.render('tags', {
            login: req.login,
            title: "标签",
            tags: tags,
            sidebar: {
                recent, tags: tags.slice(0, tagCount)
            }
        });
    }).catch(err => res.redirect("/"));
});

renderer.all('/archive', (req, res) => {
    let recentCount = Number(conf.sidebar ? conf.sidebar.recentCount : 6),
        tagCount = Number(conf.sidebar ? conf.sidebar.tagCount : 6);
    Promise.all([
        articleDB.recentArticles(recentCount),
        articleDB.findSomeTags(tagCount),
        articleDB.find({}, (col) => col.sort({top: -1, time: -1}))
    ]).then(vals => {
        let tags = vals[1],
            recent = vals[0],
            list = vals[2];

        res.render('tag', {
            login: req.login,
            title: "归档",
            articles: list.map(x => Object.assign(x, {time: moment(x.time).format(FORMAT), id: x._id})),
            sidebar: {
                recent, tags
            }
        });
    }).catch(err => res.redirect("/"));
});

renderer.all('/tag/:name', (req, res) => {
    let recentCount = Number(conf.sidebar ? conf.sidebar.recentCount : 6),
        tagCount = Number(conf.sidebar ? conf.sidebar.tagCount : 6);
    Promise.all([
        articleDB.recentArticles(recentCount),
        articleDB.findSomeTags(tagCount),
        articleDB.find({tags: req.params.name}, (col) => col.sort({top: -1, time: -1}))
    ]).then(vals => {
        let tags = vals[1],
            recent = vals[0],
            list = vals[2];

        res.render('tag', {
            login: req.login,
            title: "标签：" + req.params.name,
            articles: list.map(x => Object.assign(x, {time: moment(x.time).format(FORMAT), id: x._id})),
            sidebar: {
                recent, tags
            }
        });
    }).catch(err => res.redirect("/"));
});

module.exports = renderer;